<template>
  <div class="pagepattern">
    <div class="pagepattern-top">
      <div class="left">
        <!-- breadbrumbs -->
        <el-breadcrumb separator-class="el-icon-arrow-right">
          <el-breadcrumb-item
            v-for="(item, index) in state.breadcrumbArray"
            :to="{ path: item.path }"
            :key="index"
            >{{ item.meta.title }}</el-breadcrumb-item
          >
        </el-breadcrumb>
      </div>
      <div class="right">
        <span>{{ nowDate }}</span>
      </div>
    </div>
    <div class="div-mytable">
      <!-- table -->
      <MyTable
        :tableTitle="tableTitle"
        :tableData="tableData"
        :tableCols="tableCols"
        :tableRowAdd="tableRowAdd"
        :tableRowDelete="tableRowDelete"
        :tableRowEdit="tableRowEdit"
        :isReadonly="false"
        :tableSort="tableSort"
        :uploadProjectResource="uploadProjectResource"
        tableID="myTable"
      />
    </div>
  </div>
  <!-- add or edit a tableItem -->
  <el-dialog
    v-model="isShowDialog"
    :title="dialogTitle"
    :width="isShowProjectsDialog ? '90%' : '80%'"
    :close-on-click-modal="false"
    center
  >
    <MyTable
      :tableTitle="`培训项目`"
      :tableData="projectList"
      :tableCols="projectsTablePattern"
      :isReadonly="true"
      :tableSort="tableSort"
      :tableRowEdit="selectProject"
      tableID="select-project-table"
      v-if="isShowProjectsDialog"
    />
    <MyForm
      v-else
      :formPattern="formPattern"
      :myForm="form"
      :rules="rules"
      :validSubmit="validSubmit"
    />
  </el-dialog>
  <!-- todo -->
  <el-dialog
    v-model="isShowProjectResourcesDialog"
    title="附件"
    width="80%"
    :close-on-click-modal="false"
    center
  >
    <ProjectResource />
  </el-dialog>
  <!-- system general setting, admin only -->
  <!-- <div v-if="routeName == 'adminsystem'">
    <SystemGeneralSetting />
  </div> -->
</template>

<script lang="ts">
import {
  defineComponent,
  PropType,
  ref,
  computed,
  reactive,
  onMounted,
  watch
} from "vue";
import { useRoute, useRouter } from "vue-router";
import store from "@/store";
import MyForm from "@/components/MyForm";
import MyTable from "@/components/MyTable";
import ProjectResource from "@/components/ProjectResource";
import { constObjs } from "@/const/const";
import { ElMessage } from "element-plus";
import { sortByCreatedDate, getFormattedTime } from "@/functions/general";

import {
  upDateIncomeStreamToDb,
  deleteIncomeStreamInDb,
  addIncomeStreamToDb,
  queryAllIncomeStream
} from "@/api/incomestreamApi";

import {
  updateOutlayStreamToDb,
  deleteOutlayStreamInDb,
  addOutLayStreamToDb,
  queryAllOutlayStream
} from "@/api/outlaystreamApi";

import {
  updateProjectToDb,
  deleteProjectFromDb,
  addProjectToDb,
  queryAllProject
} from "@/api/projectApi";

import {
  IncomeStream,
  OutlayStream,
  Project,
  LandingAgency,
  Partners,
  User,
  ProjectResources
} from "@/interface/entity";
import { FormPattern } from "@/interface/general";
import {
  addUserToDb,
  deleteUserFromDb,
  queryAllUser,
  updateUserToDb
} from "@/api/userApi";
import {
  incomeStreamRules,
  outlayStreamRules,
  projectRules,
  userPermissionRules
} from "@/const/rules";

export default defineComponent({
  name: "PagePattern",
  components: {
    MyForm,
    MyTable,
    ProjectResource
  },
  props: {
    // table props
    tableData: {
      type: Array,
      required: true
    },
    tableCols: {
      type: Array,
      required: true
    },
    // form pattern
    formPattern: {
      // 从显式类型推断 props
      type: Object as PropType<FormPattern>,
      required: true
    }
    // the form data is a row of the table
  },
  setup() {
    // router
    const route = useRoute();
    const router = useRouter();

    // breadxxxs
    const state = reactive({
      // emmm.. typescript
      breadcrumbArray: [] as typeof route.matched
    });
    // onMounted
    onMounted(() => {
      const matched = route.matched; // 获取菜单对应的路由
      state.breadcrumbArray = matched;
    });
    const tableTitle = ref<string>("");
    switch (route.name) {
      case "projectsystem": {
        tableTitle.value = "培训项目";
        break;
      }

      case "adminsystem": {
        tableTitle.value = "用户信息";
        break;
      }
    }

    // watch
    watch(
      () => route.matched,
      newVal => {
        const matched = newVal;
        // 更新路由菜单数组
        state.breadcrumbArray = matched;
        switch (route.name) {
          case "projectsystem": {
            tableTitle.value = "培训项目";
            break;
          }
          case "incomestreamsystem": {
            tableTitle.value = "收入流水";
            break;
          }
          case "outlaystreamsystem": {
            tableTitle.value = "支出流水";
            break;
          }
          case "adminsystem": {
            tableTitle.value = "用户信息";
            break;
          }
        }
      }
    );

    // is show dialog
    const isShowDialog = ref<boolean>(false);
    // title of dialog
    const dialogTitle = ref<string>("");
    // is show the select projecyt dialog
    const isShowProjectsDialog = ref<boolean>(false);
    // is show project resource dialog
    const isShowProjectResourcesDialog = ref<boolean>(false);
    // now the form is updating/(adding) data
    const isEditingForm = ref<boolean>(false);

    // before add a stream, we should select a project(when click a row)
    const selectProject = (row: object, index: number) => {
      store.state.selectedProject = row as Project;
      isEditingForm.value = false;
      // generate landingAgencies and partners from project
      // todo client
      const clients = JSON.parse(
        JSON.stringify(store.state.selectedProject.clients)
      ) as LandingAgency[];
      const agencies = JSON.parse(
        JSON.stringify(store.state.selectedProject.landingAgencies)
      ) as LandingAgency[];
      const partners = JSON.parse(
        JSON.stringify(store.state.selectedProject.partners)
      ) as Partners[];

      // here to init the shareamout to 0!!!
      // todo client
      clients.forEach(agency => (agency.shareAmount = 0));
      agencies.forEach(agency => (agency.shareAmount = 0));
      partners.forEach(partner => (partner.shareAmount = 0));
      // the landingAgencies and partners of the project will copy to the stream which will be created
      if (route.name == "incomestreamsystem") {
        // todo client
        (store.state.editingForm as IncomeStream).clients = agencies;
        (store.state.editingForm as IncomeStream).landingAgencies = agencies;
        (store.state.editingForm as IncomeStream).partners = partners;
        store.state.formPattern = JSON.parse(
          JSON.stringify(constObjs.incomeStreamFormPattern)
        );
      }
      if (route.name == "outlaystreamsystem") {
        // todo client
        (store.state.editingForm as OutlayStream).clients = agencies;
        (store.state.editingForm as OutlayStream).landingAgencies = agencies;
        (store.state.editingForm as OutlayStream).partners = partners;
        store.state.formPattern = JSON.parse(
          JSON.stringify(constObjs.outlayStreamFormPattern)
        );
      }
      // after selected, show the add stream dialog(form),and hide the selectproject dialog
      isShowProjectsDialog.value = false;
      isShowDialog.value = true;
    };

    // add row
    const tableRowAdd = () => {
      // now is adding a row
      isEditingForm.value = false;

      switch (route.name) {
        case "projectsystem": {
          if (store.state.nowUserPermissionList.includes("addProject")) {
            store.state.formPattern = JSON.parse(
              JSON.stringify(constObjs.projectFormPattern)
            );

            store.state.editingForm = JSON.parse(
              JSON.stringify(constObjs.projectForm)
            );
            // if now is projectsystem, the dialog will show after the add button is clicked
            store.state.formRules = JSON.parse(JSON.stringify(projectRules));
            isShowDialog.value = true;
          } else {
            ElMessage.error(
              `您当前的账户:[${store.state.username}]无权限使用此功能，请联系管理员管理该账户权限`
            );
          }
          break;
        }
        case "incomestreamsystem": {
          if (store.state.nowUserPermissionList.includes("addIncomeStream")) {
            store.state.editingForm = JSON.parse(
              JSON.stringify(constObjs.incomeStreamForm)
            );
            store.state.formPattern = JSON.parse(
              JSON.stringify(constObjs.incomeStreamFormPattern)
            );
            store.state.formRules = JSON.parse(
              JSON.stringify(incomeStreamRules)
            );
            // if not projectsystem, select a project first
            isShowDialog.value = true;
            isShowProjectsDialog.value = true;
          } else {
            ElMessage.error(
              `您当前的账户:[${store.state.username}]无权限使用此功能，请联系管理员管理该账户权限`
            );
          }
          break;
        }
        case "outlaystreamsystem": {
          if (store.state.nowUserPermissionList.includes("addOutlayStream")) {
            store.state.editingForm = JSON.parse(
              JSON.stringify(constObjs.outlayStreamForm)
            );
            store.state.formPattern = JSON.parse(
              JSON.stringify(constObjs.outlayStreamFormPattern)
            );
            store.state.formRules = JSON.parse(
              JSON.stringify(outlayStreamRules)
            );
            // if not projectsystem, select a project first
            isShowDialog.value = true;
            isShowProjectsDialog.value = true;
          } else {
            ElMessage.error(
              `您当前的账户:[${store.state.username}]无权限使用此功能，请联系管理员管理该账户权限`
            );
          }
          break;
        }
        case "adminsystem": {
          store.state.formRules = JSON.parse(
            JSON.stringify(userPermissionRules)
          );
          store.state.editingForm = JSON.parse(
            JSON.stringify(constObjs.userPermissionForm)
          );
          isShowDialog.value = true;
          break;
        }
      }
    };

    // edit row
    const tableRowEdit = (row: object, index: number) => {
      const user = store.state.nowUser;
      // now is editing form
      isEditingForm.value = true;
      // save now rowindex
      store.state.selectedRowIndex = index;
      // update the store
      switch (route.name) {
        case "incomestreamsystem": {
          // show the dialog of the farther component
          isShowDialog.value = true;
          if (
            store.state.nowUserPermissionList.includes(
              "updateIncomeStream" || user.userRole == "admin"
            )
          ) {
            // title
            dialogTitle.value = "编辑收入流水";
            store.state.editingForm = JSON.parse(
              JSON.stringify(row)
            ) as IncomeStream;
            // 记录变化前的入账金额
            store.state.editingForm.oldIncomeAmount = JSON.parse(
              JSON.stringify(store.state.editingForm.incomeAmount)
            );
            store.state.formRules = JSON.parse(
              JSON.stringify(incomeStreamRules)
            );
            store.state.formPattern = JSON.parse(
              JSON.stringify(constObjs.incomeStreamFormPattern)
            );
          } else {
            ElMessage.error(
              `您当前的账户:[${store.state.username}]无权限使用此功能，请联系管理员管理该账户权限`
            );
          }
          break;
        }
        case "outlaystreamsystem": {
          if (
            store.state.nowUserPermissionList.includes(
              "updateOutlayStream" || user.userRole == "admin"
            )
          ) {
            // show the dialog of the farther component
            isShowDialog.value = true;
            // title
            dialogTitle.value = "编辑支出流水";
            store.state.editingForm = JSON.parse(
              JSON.stringify(row)
            ) as OutlayStream;
            // 记录变化前的支出合计
            store.state.editingForm.oldTotalPay = JSON.parse(
              JSON.stringify(store.state.editingForm.totalPay)
            );
            store.state.formRules = JSON.parse(
              JSON.stringify(outlayStreamRules)
            );
            store.state.formPattern = JSON.parse(
              JSON.stringify(constObjs.outlayStreamFormPattern)
            );
          } else {
            ElMessage.error(user.userRole);
            ElMessage.error(
              `您当前的账户:[${store.state.username}]无权限使用此功能，请联系管理员管理该账户权限`
            );
          }
          break;
        }
        case "projectsystem": {
          // MAKE SURE THAT only change the tabledata when update db
          if (
            store.state.nowUserPermissionList.includes("updateProject") ||
            user.userRole == "admin"
          ) {
            const projectForm = JSON.parse(JSON.stringify(row)) as Project;
            // 所属地变为数组
            projectForm.selectedArea = (projectForm.selectedArea as string).split(
              " "
            );
            store.state.editingForm = projectForm;
            // title
            dialogTitle.value = "编辑项目";
            store.state.formPattern = JSON.parse(
              JSON.stringify(constObjs.projectFormPattern)
            );
            store.state.formRules = JSON.parse(JSON.stringify(projectRules));

            // show the dialog of the farther component
            isShowDialog.value = true;
          } else {
            ElMessage.error(
              `您当前的账户:[${store.state.username}]无权限使用此功能，请联系管理员管理该账户权限`
            );
          }
          break;
        }
        case "adminsystem": {
          dialogTitle.value = "编辑用户信息";
          store.state.editingForm = JSON.parse(JSON.stringify(row)) as User;
          // show the dialog of the farther component
          isShowDialog.value = true;
          isEditingForm.value = true;
          store.state.formRules = JSON.parse(
            JSON.stringify(userPermissionRules)
          );
          store.state.formPattern = JSON.parse(
            JSON.stringify(constObjs.userPermissionFormPattern)
          );
          break;
        }
      }
    };

    // batch delete
    const tableRowDelete = async (rows: object[]) => {
      const user = store.state.nowUser;
      switch (route.name) {
        case "incomestreamsystem": {
          if (
            store.state.nowUserPermissionList.includes(
              "deleteIncomeStream" || user.userRole == "admin"
            )
          ) {
            // base on the primary key which is exist when deleting this stream

            await Promise.all(
              rows.map(async row => {
                await deleteIncomeStreamInDb(row as IncomeStream);
              })
            ).then(() => {
              ElMessage.success(`删除成功,本次共删除了${rows.length}条记录`);
            });

            // update the data(because the table head will changed when delete a incomestream item)
            await queryAllIncomeStream();
          } else {
            ElMessage.error(
              `您当前的账户:[${store.state.username}]无权限删除收入流水，请联系管理员管理该账户权限`
            );
          }
          break;
        }
        case "outlaystreamsystem": {
          if (
            store.state.nowUserPermissionList.includes("deleteOutlayStream") ||
            user.userRole == "admin"
          ) {
            // base on the primary key which is exist when deleting this stream
            await Promise.all(
              rows.map(async row => {
                await deleteOutlayStreamInDb(row as OutlayStream);
              })
            );
            ElMessage.success(`删除成功,本次共删除了${rows.length}条记录`);
            await queryAllOutlayStream();
          } else {
            ElMessage.error(
              `您当前的账户:[${store.state.username}]无权限删除收入流水，请联系管理员管理该账户权限`
            );
          }
          break;
        }
        case "projectsystem": {
          if (
            store.state.nowUserPermissionList.includes("deleteProject") ||
            user.userRole == "admin"
          ) {
            // to db
            await Promise.all(
              rows.map(async row => {
                await deleteProjectFromDb(row as Project);
              })
            ).then(() => {
              ElMessage.success(`删除成功,本次共删除了${rows.length}条记录`);
            });
            // update the data(because the table head maybe changed when delete a project item)
            await queryAllProject();
          } else {
            ElMessage.error(
              `您当前的账户:[${store.state.username}]无权限删除培训项目，请联系管理员管理该账户权限`
            );
          }
          break;
        }
        case "adminsystem": {
          // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
          rows.forEach(async row => {
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            await deleteUserFromDb((row as User).userID!);
          });
          await queryAllUser();
        }
      }
    };

    // submit form when it's validate
    // add(or update) form
    const validSubmit = async () => {
      switch (route.name) {
        case "incomestreamsystem": {
          const form = store.state.editingForm as IncomeStream;
          // store will be updated when editing stream
          // update or add to db
          if (isEditingForm.value) {
            await upDateIncomeStreamToDb(form);
          } else {
            await addIncomeStreamToDb(form);
          }
          setTimeout(() => {
            queryAllIncomeStream();
            // update pattern
            store.state.tablePattern = JSON.parse(
              JSON.stringify(constObjs.incomeStreamTablePattern)
            );
          }, 200);
          break;
        }
        case "outlaystreamsystem": {
          const form = store.state.editingForm as OutlayStream;
          // 格式化日期
          // update or add to db
          if (isEditingForm.value) {
            await updateOutlayStreamToDb(form);
          } else {
            // projectguid and categories
            await addOutLayStreamToDb(form);
          }
          await queryAllOutlayStream();
          break;
        }
        case "projectsystem": {
          const form = store.state.editingForm as Project;

          // update or add to db
          if (isEditingForm.value) {
            await updateProjectToDb(form);
            // query the project after updated and update the store
          } else {
            await addProjectToDb(form);
          }
          await queryAllProject();
          // update
          store.state.tablePattern = JSON.parse(
            JSON.stringify(constObjs.projectsTablePattern)
          );
          break;
        }
        case "adminsystem": {
          const form = store.state.editingForm as User;
          if (isEditingForm.value) {
            await updateUserToDb(form);
            queryAllUser();
          } else {
            await addUserToDb(form);
            await queryAllUser();
          }
        }
      }
      isShowDialog.value = false;
      isShowProjectsDialog.value = false;
    };

    // row is project
    async function uploadProjectResource(row: object) {
      const nowProject = row as Project,
        user = store.state.nowUser;

      if (
        user.username == nowProject.projectManager ||
        user.userRole == "admin"
      ) {
        const projectGuid = (row as Project).projectGuid;
        // query files if have permission
        if (store.state.nowUser.permissionString.includes("projectResource")) {
          // todo query when click a row
          // init state(not delete the guid)
          store.state.projectResources.resources = (JSON.parse(
            JSON.stringify(constObjs.projectResources)
          ) as ProjectResources).resources;
          // get projectguid
          store.state.projectResources.projectGuid = projectGuid;
          // show resource dialog
          isShowProjectResourcesDialog.value = true;
        } else {
          ElMessage.error("该项目负责人没有操作项目附件的权限，请联系管理员");
        }
      } else {
        ElMessage.error("当前账户名称与该项目的项目负责人不匹配，无法上传附件");
      }
    }

    return {
      route,
      routeName: computed(() => route.name),
      router,
      state,
      nowDate: computed(() => getFormattedTime("nowtime")),
      tableTitle,
      isShowDialog,
      isShowProjectsDialog,
      isShowProjectResourcesDialog,
      dialogTitle,
      isEditingForm,
      selectProject,
      tableRowAdd,
      tableRowEdit,
      tableRowDelete,
      uploadProjectResource,
      validSubmit,
      // select a sort function base on route.name
      tableSort: computed(() => sortByCreatedDate),
      // 编辑的时候直接操作store
      form: computed(() => store.state.editingForm),
      rules: computed(() => store.state.formRules),
      projectList: computed(() => store.state.projectList),
      projectsTablePattern: computed(() => constObjs.projectsTablePattern)
    };
  }
});
</script>

<style scoped>
.pagepattern-top {
  display: flex;
  align-items: center;
  flex-direction: row;
  width: 100%;
  height: 30px;
  margin-bottom: 20px;
  background-color: rgb(245, 245, 246);
  box-shadow: -1px 1px 1px 0px #ccc, 1px -1px 1px 0px #ccc,
    -1px -1px 1px 0px #ccc, 1px 1px 1px 0px #ccc;
}
.pagepattern-top .el-breadcrumb {
  font-size: 14px;
  margin-left: 20px;
}
.pagepattern-top .right {
  margin-left: auto;
  margin-right: 24px;
  font-size: 14px;
}
/* -------------------------通用样式-------------------- */
ul {
  margin: 0;
}
/* li不在在一行显示 */
li {
  display: block;
}
</style>
